For any suggestions or feedback regarding these notes,
please contact Pragy Agarwal
Different types of NoSQL databases specialize for specific features & use-cases.
Be careful about the features you see being claimed by popular NoSQL databases.
Simplest type of NoSQL database.
Think of it as just a giant hashmap distributed across servers
Keys & Values (hashmap)
Both the key & the value are just plain strings (the database doesn't know & doesn't care about what is contained inside those)
Violated by most modern key-value stores.
Key | Value |
"contest:13:page:10" | "{ |
"contest:13:winner" | 1361 |
Imagine that you’re storing a counter inside the key-value db.
How will you increment it?
In your application code
value = key_value_db.get(key)
value += 1
key_value_db.set(value)
If you increment the counter in this manner, it will lead to a race condition.
Modern databases like Redis allow you to do much more than these 3 simple operations.
Typically increment == Get + Set.
But redis allows you to do this in a single inc operation
Automatically sharded by the hash(key)
In Redis any string has a limitation of max 500 MB.
Q: Does this mean that storing 500MB of data per entry is a good idea?
Absolutely NO!
To use key-value database, your keys <≈ 100 bytes, values <≈ 10 KB
If your keys are longer than 100 bytes, then perhaps you should look at some other database.
if your value is > 10Kb, then you probably need to dive deeper into the value – key-value is probably a poor choice.
Storing unstructured / semi-structured data.
Think of this as a collection of json/jsonb files distributed across multiple servers.
A single document will never be sharded — a single document is always stored completely within a single server (+ replicated across multiple servers)
MongoDB, ElasticSearch, Couchbase, ...
{
_id: uuidv4
product_id: int
name: string
type: string (t-shirt)
brand: string
color: string
neck_type: byte
sleeve_length: byte
image_url: string
}
{
_id: uuidv4
product_id: int
name: string
type: string (laptop)
brand: string
color: string
ram: {
size: integer
technology: string (ddr4/ddr5/..)
cas_latency: string
}
cpu: string
image_url: [string, string, string]
}
Every document in mongodb has a unique document id.
Any document can have any set of attributes.
_id is automatically created on the client side when the document is being inserted
mongoClient.find( {_id: "..."} ) will fetch the document with the given document_id
mongoClient.find( {brand: "dell"} ) will fetch the documents where the value of the attribute "brand" is equal to "dell"
The default sharding key (if nothing else is configured) is _id
But any top-level attribute (or composite of top-level attributes) can be configured as the sharding key.
For example: for the amazon products listing we could set the sharding key as product_type (laptop/tshirt/...)
Documents should <≈ 10MB
MongoDB has a cap of 16MB for their documents
Because any read/write inside a document database is at the document level.
If you modify even 1 character inside 1 attribute of a 16MB document, the database will completely rewrite this document.
You cannot modify individual attributes/values inside the document.
Similar when you read the document, you cannot read just a particular attribute of the document - the database will always read the entire document from disk.
For example,
What is the size of the boolean data type (doesn’t matter what programming language)
Why? Are programmers stupid? Are people who created these languages stupid?
No.
Your HDD/RAM/CPU Cache/Registers .. any memory is “byte addressable”. You can read/write individual bytes, but you can NEVER read/write individual bits.
Similarly,
Wide-Column, Column Family, Columnar, … all of these are the same thing
Timeseries database are just a subset (special type) of Wide-column databases.
The data is still tabular in format (just like relational databases)
However
Timeseries DBs are a subcategory of wide-columns DBs
Cassandra (popular), BigTable (first NoSQL db ever), ScyllaDB, HBase, ...
Every column family database models data in a very different manner!
The common thing is that all of them will store the data in tables, and these tables will be “partitioned” (sharded) across the servers.
(same as previous - no joins, no relations, no search, no indexes…)
1. Try online: https://jbcodeforce.github.io/db-play/
2. Introduction: https://cassandra.apache.org/_/cassandra-basics.html
3. Case Studies: https://cassandra.apache.org/_/case-studies.html
4. Architecture - Overview: https://cassandra.apache.org/doc/stable/cassandra/architecture/overview.html
5. Architecture - Guarantees: https://cassandra.apache.org/doc/stable/cassandra/architecture/guarantees.html
6. Data Modeling: Introduction | Apache Cassandra Documentation
Flat files directly on the disk (files are chunked & distributed across servers).
The same file can be split across multiple servers.
Famous, because people have a weird attraction to graphs
But rare in practice!
Good when your queries require "path-finding"
More popular due to AI
Provide fast K-Nearest Neighbor queries - extremely useful for searching over an embedding space
Table inheritance (postgres)
.... every kid and their grandmother have their own NoSQL database type.
All modern database are multi-modal - they provide multiple features.
scale is too large!
For popular hashtags like #US-Elections-2025, #Diwali, ... a single server won't be able to store all the tweets (even for 1 hashtag)
Key? "#Diwali2025 : popular" or "#Diwali2025: recent"
Value? all the top-100 popular/recent tweets for the hashtag, or all the tweets for the hashtag
Same reasons as key-value
{
__doc_id: ….
hashtag: “Diwali 2025”
tweets: [
{user_id: … , … , },
{user_id: … , … , },
{user_id: … , … , },
]
}
{
__doc_id: == tweet_id
hashtag: “Diwali 2025”
content: “Celebrating crackerless pollution less diwali <3”
author_id: Krishna
likeCount: 1234
viewCount: 12322
}
HBase for example
All our requirements match exactly with the strengths of Column Family DBs.